package com.sync.platform.controller;

import com.sync.platform.entity.ServerConfig;
import com.sync.platform.entity.SyncTask;
import com.sync.platform.service.ServerConfigService;
import com.sync.platform.service.SyncTaskService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Map;
import java.util.HashMap;
import java.util.ArrayList;
import java.util.Vector;
import java.io.IOException;
import java.util.Collections;
import java.util.Comparator;

import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.SftpException;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.ChannelSftp;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * File synchronization controller
 */
@Controller
@RequestMapping("/sync/file")
public class FileSyncController {

    private static final Logger logger = LoggerFactory.getLogger(FileSyncController.class);

    @Autowired
    private SyncTaskService syncTaskService;

    @Autowired
    private ServerConfigService serverConfigService;

    /**
     * File sync task list page
     */
    @GetMapping({"", "/"})
    public String list(Model model) {
        List<SyncTask> tasks = syncTaskService.getFileSyncTasks();
        Map<Long, ServerConfig> serverMap = new HashMap<>();
        
        // 获取所有服务器信息
        List<ServerConfig> allServers = serverConfigService.list();
        for (ServerConfig server : allServers) {
            serverMap.put(server.getId(), server);
        }
        
        // 将服务器信息添加到Model中
        model.addAttribute("tasks", tasks);
        model.addAttribute("serverMap", serverMap);
        return "sync/file/list";
    }

    /**
     * New file sync task page
     */
    @GetMapping("/new")
    public String newTask(Model model) {
        List<ServerConfig> servers = serverConfigService.list();
        model.addAttribute("servers", servers);
        return "sync/file/edit";
    }

    /**
     * Edit file sync task page
     */
    @GetMapping("/edit/{id}")
    public String edit(@PathVariable Long id, Model model) {
        SyncTask task = syncTaskService.getById(id);
        if (task == null) {
            return "redirect:/sync/file";
        }
        
        List<ServerConfig> servers = serverConfigService.list();
        model.addAttribute("task", task);
        model.addAttribute("servers", servers);
        return "sync/file/edit";
    }

    /**
     * Save file sync task
     */
    @PostMapping("/save")
    @ResponseBody
    public Map<String, Object> save(
            @RequestParam(required = false) Long id,
            @RequestParam String name,
            @RequestParam Integer taskType,
            @RequestParam Long sourceId,
            @RequestParam Long targetId,
            @RequestParam(required = false) String cronExpression,
            @RequestParam Integer status,
            @RequestParam String sourcePath,
            @RequestParam String targetPath,
            @RequestParam(required = false) String filePattern,
            @RequestParam(required = false, defaultValue = "ssh") String transferType,
            @RequestParam(required = false, defaultValue = "false") String deleteSource,
            @RequestParam(required = false, defaultValue = "false") String syncDirectories) {
        
        // Create SyncTask object
        SyncTask syncTask = new SyncTask();
        if (id != null) {
            syncTask.setId(id);
        }
        syncTask.setName(name);
        syncTask.setTaskType(taskType);
        syncTask.setSourceId(sourceId);
        syncTask.setTargetId(targetId);
        syncTask.setCronExpression(cronExpression);
        syncTask.setStatus(status);
        
        return syncTaskService.saveFileSyncTask(syncTask, sourcePath, targetPath, filePattern, transferType, deleteSource, syncDirectories);
    }

    /**
     * Execute file sync task
     */
    @PostMapping("/execute/{id}")
    @ResponseBody
    public Map<String, Object> execute(@PathVariable Long id) {
        return syncTaskService.executeTask(id);
    }

    /**
     * Delete file sync task
     */
    @PostMapping("/delete/{id}")
    @ResponseBody
    public Map<String, Object> delete(@PathVariable Long id) {
        boolean success = syncTaskService.removeById(id);
        Map<String, Object> result = new HashMap<>();
        result.put("success", success);
        return result;
    }

    /**
     * Browse server directory
     */
    @GetMapping("/browse-directory")
    @ResponseBody
    public Map<String, Object> browseDirectory(
            @RequestParam Long serverId,
            @RequestParam(required = false, defaultValue = "/") String path) {
        
        Map<String, Object> result = new HashMap<>();
        List<Map<String, Object>> directories = new ArrayList<>();
        
        try {
            ServerConfig server = serverConfigService.getById(serverId);
            if (server == null) {
                result.put("success", false);
                result.put("message", "服务器不存在");
                return result;
            }
            
            // Ensure path ends with a slash for consistency
            if (!path.endsWith("/")) {
                path += "/";
            }
            
            // Default transfer type to ssh if not specified
            String transferType = server.getTransferType() != null ? server.getTransferType() : "ssh";
            
            if ("ssh".equals(transferType)) {
                // SSH/SFTP browse
                Session session = null;
                ChannelSftp channelSftp = null;
                
                try {
                    session = com.sync.platform.util.SSHUtil.createSession(
                        server.getHost(),
                        server.getPort(),
                        server.getUsername(),
                        server.getPassword(),
                        server.getPrivateKeyPath()
                    );
                    session.connect();
                    
                    channelSftp = (ChannelSftp) session.openChannel("sftp");
                    channelSftp.connect();
                    
                    @SuppressWarnings("unchecked")
                    Vector<ChannelSftp.LsEntry> entries = channelSftp.ls(path);
                    
                    for (ChannelSftp.LsEntry entry : entries) {
                        // Skip . and .. entries
                        if (".".equals(entry.getFilename()) || "..".equals(entry.getFilename())) {
                            continue;
                        }
                        
                        if (entry.getAttrs().isDir()) {
                            Map<String, Object> dir = new HashMap<>();
                            dir.put("name", entry.getFilename());
                            dir.put("path", path + entry.getFilename());
                            dir.put("isDirectory", true);
                            directories.add(dir);
                        }
                    }
                    
                    // Sort directories by name
                    Collections.sort(directories, Comparator.comparing(d -> (String) d.get("name")));
                    
                    result.put("success", true);
                    result.put("currentPath", path);
                    result.put("directories", directories);
                    
                } catch (JSchException | SftpException e) {
                    logger.error("Error browsing SFTP directory: {}", e.getMessage(), e);
                    result.put("success", false);
                    result.put("message", "浏览目录失败: " + e.getMessage());
                } finally {
                    if (channelSftp != null && channelSftp.isConnected()) {
                        channelSftp.disconnect();
                    }
                    if (session != null && session.isConnected()) {
                        session.disconnect();
                    }
                }
            } else if ("ftp".equals(transferType)) {
                // FTP browse
                FTPClient ftpClient = null;
                
                try {
                    ftpClient = com.sync.platform.util.FTPUtil.connect(
                        server.getHost(),
                        server.getPort(),
                        server.getUsername(),
                        server.getPassword()
                    );
                    
                    // Try to change to the directory
                    if (!ftpClient.changeWorkingDirectory(path)) {
                        result.put("success", false);
                        result.put("message", "目录不存在或无权限访问");
                        return result;
                    }
                    
                    FTPFile[] ftpFiles = ftpClient.listFiles();
                    
                    for (FTPFile ftpFile : ftpFiles) {
                        // Skip . and .. entries
                        if (".".equals(ftpFile.getName()) || "..".equals(ftpFile.getName())) {
                            continue;
                        }
                        
                        if (ftpFile.isDirectory()) {
                            Map<String, Object> dir = new HashMap<>();
                            dir.put("name", ftpFile.getName());
                            dir.put("path", path + ftpFile.getName());
                            dir.put("isDirectory", true);
                            directories.add(dir);
                        }
                    }
                    
                    // Sort directories by name
                    Collections.sort(directories, Comparator.comparing(d -> (String) d.get("name")));
                    
                    result.put("success", true);
                    result.put("currentPath", path);
                    result.put("directories", directories);
                    
                } catch (IOException e) {
                    logger.error("Error browsing FTP directory: {}", e.getMessage(), e);
                    result.put("success", false);
                    result.put("message", "浏览目录失败: " + e.getMessage());
                } finally {
                    if (ftpClient != null && ftpClient.isConnected()) {
                        try {
                            ftpClient.disconnect();
                        } catch (IOException e) {
                            logger.error("Error disconnecting FTP client: {}", e.getMessage(), e);
                        }
                    }
                }
            } else {
                result.put("success", false);
                result.put("message", "不支持的传输类型: " + transferType);
            }
            
        } catch (Exception e) {
            logger.error("Error browsing directory: {}", e.getMessage(), e);
            result.put("success", false);
            result.put("message", "浏览目录失败: " + e.getMessage());
        }
        
        return result;
    }

    /**
     * 测试文件模式匹配
     */
    @GetMapping("/test-pattern")
    @ResponseBody
    public Map<String, Object> testPattern(
        @RequestParam String fileName,
        @RequestParam String pattern) {
        
        Map<String, Object> result = new HashMap<>();
        String[] patterns = com.sync.platform.util.FilePatternUtil.parsePatterns(pattern);
        
        result.put("fileName", fileName);
        result.put("pattern", pattern);
        
        if (patterns != null) {
            List<Map<String, Object>> patternResults = new ArrayList<>();
            for (String p : patterns) {
                Map<String, Object> patternResult = new HashMap<>();
                patternResult.put("pattern", p);
                patternResult.put("description", com.sync.platform.util.FilePatternUtil.getPatternDescription(p));
                patternResult.put("matches", com.sync.platform.util.FilePatternUtil.matchPattern(fileName, p));
                patternResults.add(patternResult);
            }
            result.put("patternResults", patternResults);
        }
        
        result.put("matches", com.sync.platform.util.FilePatternUtil.matchAnyPattern(fileName, patterns));
        return result;
    }
} 